let effectStack = []; //存储收集的依赖

// 存储所有的reactive以及其中的所有的key所对应的依赖
let tartgetMap = new WeakMap();

// 收集依赖
function track(target, key) {
  const effect = effectStack[effectStack.length - 1];
  if (effect) {
    // 查看当前reactive传入的对象的依赖
    let depMap = Reflect.get(tartgetMap, target);
    // 如果它的map不存在，则我们需要对其进行初始化
    if (!depMap) {
      depMap = new Map();
      Reflect.set(tartgetMap, target, depMap);
    }
    // 尝试获取它的effect
    let dep = Reflect.get(depMap, key);
    // 如果dep也不存在，则我们需要对其进行初始化
    if (!dep) {
      dep = new Set();
      Reflect.set(depMap, key, dep);
    }
    // 执行到这边，我们可以理解为，当前这个reactive的依赖的一个map结构已经初始化完毕

    // 依赖添加,困为采用的是一个set的数据结构，所以不用考虑一个重复的问题
    dep.add(effect);

    //这里就是相当于让effect也有一个deps对象，让它知道它是依赖的谁，双向存储
    effect.deps.push(dep);
  }
}

// 触发更新
function trigger(target, key, info) {
  let depMap = Reflect.get(tartgetMap, target);
  // 没有依赖，就直接return就行了
  if (!depMap) {
    return;
  }
  const effectRunner = new Set();
  const computedRunner = new Set();
  if (key) {
    // 获取之前存储的依赖的集合
    let deps = Reflect.get(depMap, key);
    deps.forEach((effect) => {
      if (effect.computed) {
        computedRunner.add(effect);
      } else {
        effectRunner.add(effect);
      }
    });
  }
  effectRunner.forEach((effect) => {
    console.log(effect);
    effect();
  });
  computedRunner.forEach((computed) =>{
    console.log(computed)
    computed()
  });
}

const baseHandler = {
  get(target, key) {
    const res = Reflect.get(target, key);
    // 收集依赖
    track(target, key);
    return res;
  },
  set(target, key, val) {
    const info = { oldValue: target[key], newValue: val };
    Reflect.set(target, key, val);
    // 触发更新
    trigger(target, key, info);
  },
};

function reactive(target) {
  // 将target变成响应式
  const observerd = new Proxy(target, baseHandler);
  return observerd;
}

// effect
function effect(fn, option = {}) {
  // 第一个fn不用赘述，第二个options它的值可以是{lazy:false,computed:false}
  // 其实computed它就是一个特殊的effect

  let e = createReactiveEffect(fn, option);
  console.log(e())

  // 这里需要通过判断option的lazy来决定是否首次就执行effect
  if (!option.lazy) {
    e();
  }
  return e;
}

function createReactiveEffect(fn, options) {
  // 回传
  const effect = function effect(...args) {
    return run(effect, fn, args);
  };
  // 为了后续清理 以及缓存
  effect.deps = [];
  effect.computed = options.computed;
  effect.lazy = options.lazy;
  return effect;
}

function run(effect, fn, args) {
  if (effectStack.indexOf(effect) === -1) {
    try {
      effectStack.push(effect);
      return fn(...args);
    } finally {
      effectStack.pop();
    }
  }
}

function computed(fn) {
  // 特殊的effect
  const runner = effect(fn, { computed: true, lazy: true });
  return {
    effect: runner,
    get value() {
      return runner();
    },
  };
}